<template>
  <div class="ui-tree-item">
    <div class="content"
         :class="getContentClass()"
         :draggable="draggable"
         @dragstart="onDragStart"
         @mouseenter="hover=true"
         @mouseleave="hover=false"
    >
      <div style="width: 16px;height: 16px;">
        <div class="iconfont fold"
             @click.stop.prevent="onFold"
             v-show="data.children.length"
             :class="fold?'icon-arrow-right-filling':'icon-arrow-down-filling'">
        </div>
      </div>
      <div class="name"
           @contextmenu.stop.prevent="onContextmenu"
           @dblclick="onDBClick"
           @click="onSelect">
        <div class="iconfont" :class="getIconClass()"></div>
        <div class="text">
          <label style="flex:1;display: flex;height: 100%;" v-show="isRename">
            <input ref="renameInput" class="renameInput" v-model="name"
                   @keydown.enter.prevent.stop="onInputOver"
                   @blur="onBlur">
          </label>
          <span v-show="!isRename">{{ name }}</span>
        </div>
      </div>
    </div>

    <tree-item v-show="data.children&&data.children.length&&!fold"
               class="tree-children"
               v-for="(item,index) in data.children"
               :key="index"
               :data="item"
    ></tree-item>
  </div>
</template>

<script lang="ts">
import { defineComponent, inject, nextTick, onMounted, onUnmounted, PropType, ref, toRaw, watch } from 'vue';
import { Msg, ProvideKey, TreeData } from './index';
import { Emitter } from '@/ui-kit/index';
import { IAssetInfo } from '../../views/editor/store/types';
import assetsStore from '../../views/editor/store/assets';

const TreeItemSelected = 'tree-item-selected';


export default defineComponent({
  name: 'tree-item',
  props: {
    data: {
      type: Object as PropType<TreeData>,
      required: true,
      default: () => {
        return { name: '' };
      },
    },
  },
  emits: ['context'],
  setup(props, { emit }) {
    const InjectCanDrag = inject(ProvideKey.CanDraggable, (data: any) => false);

    const fold = ref(false);
    const selected = ref(false);
    const hover = ref(false);
    onMounted(() => {
      Emitter.on(TreeItemSelected, (target: TreeData) => {
        selected.value = (target === props.data);
      });
    });

    function onFold() {
      fold.value = !fold.value;
    }

    const draggable = ref(InjectCanDrag(props.data.data));
    const dragStart = inject(ProvideKey.DragStart, (event: DragEvent, data: any) => {});

    const DoubleClickCallBack = inject(ProvideKey.DoubleClick, (data: TreeData) => {});
    const isRename = ref(false);
    const name = ref(props.data.name);
    watch(() => props.data, value => {
      name.value = value.name;
    });
    const renameInput = ref();

    const onRename = (item: IAssetInfo) => {
      isRename.value = item.id === props.data.id;
      if (isRename.value) {
        nextTick(() => {
          renameInput.value.focus();
        });
      }
    };
    onMounted(() => {
      Emitter.on(Msg.RenameItem, onRename);
    });
    onUnmounted(() => {
      Emitter.off(Msg.RenameItem, onRename);
    });

    function acceptNewName(event: any) {
      isRename.value = false;
      const fn = props.data.change;
      if (fn) {
        // todo 不太优雅
        const data = new TreeData({ name: toRaw(name.value) });
        const change = fn(event, data);
        if (!change) {
          const asset: IAssetInfo | null = assetsStore().getAsset(props.data.id);
          if (asset) {
            name.value = asset.name;
          }
        }
      }
    }

    return {
      renameInput,
      name,
      fold, selected, hover,
      isRename,
      draggable,
      onFold,
      onDragStart(event: DragEvent) {
        dragStart(event, toRaw(props.data.data));
      },
      onInputOver(event: any) {
        acceptNewName(event);
      },
      onBlur(event: MouseEvent) {
        acceptNewName(event);
      },
      getIconClass() {
        const treeData: TreeData = props.data;
        if (treeData.icon) {
          return treeData.icon;
        } else {
          if (fold.value) {
            return 'icon-folder-close';
          } else {
            return 'icon-file-open';
          }
        }
      },

      getContentClass() {
        const hoverClass = 'item-hover';
        const selectClass = 'item-selected';
        if (selected.value) {
          return selectClass;
        }

        if (hover.value) {
          return hoverClass;
        } else {
          return '';
        }
      },

      onSelect(event: MouseEvent) {
        Emitter.emit(TreeItemSelected, props.data);
        const { click } = props.data;
        if (click) {
          click(event, props.data);
        }
      },

      onDBClick(event: MouseEvent) {
        if (props.data.children.length) {
          onFold();
        } else {
          const { dblclick } = props.data;
          if (dblclick) {
            dblclick(event, props.data);
          } else {
            DoubleClickCallBack(props.data);
          }
        }
      },

      onContextmenu(event: Event) {
        const { contextmenu } = props.data;
        if (contextmenu) {
          contextmenu(event, props.data);
        } else {
          emit('context', event, props.data);
        }
      },
    };
  },
});

</script>

<style scoped lang="scss">
.ui-tree-item {
  display: flex;
  flex-direction: column;

  .item-selected {
    background-color: #aaaeb1;
  }

  .item-hover {
    background-color: #d4d8db;
  }

  .content {
    display: flex;
    flex-direction: row;
    align-items: center;


    .fold {
      cursor: pointer;
    }

    .name {
      flex: 1;
      display: flex;
      flex-direction: row;
      align-items: center;

      .text {
        height: 21px;
        flex: 1;
        margin-left: 2px;
        text-align: left;
        display: flex;
        flex-direction: row;
        align-items: center;

        span {
          user-select: none;
          text-align: left;
          font-size: 15px;
        }

        .renameInput {
          box-sizing: border-box;
          height: 100%;
          background-color: transparent;
          outline: none;
          flex: 1;
          border: 1px solid #ee773b;
        }
      }

    }

  }


  .tree-children {
    margin-left: 15px;
  }
}
</style>
